﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TN_CMS.Domain.Abstract;
using TN_CMS.Domain.Entities;
using TN_CMS.Domain.MapBuilder;
using Microsoft.Practices.EnterpriseLibrary.Data;
using TN_CMS.Domain.ResultSetMapper;

namespace TN_CMS.Domain.Concrete
{
    public class EFProductRepository : BaseRepository, IProductRepository
    {
        private readonly EFDbContext context = new EFDbContext();
        public const string TableProductGroups = "ProductGroups";
        public const string TableProducts = "Products";
        public const string ColumnId = "Id";
        public const string ColumnIsActive = "IsActive";

        #region Product

        public List<Product> GetList(int pageIndex, int pageSize, out int total, string orderClause, string whereClause)
        {
            var map = TNMapBuilder<Product>
                .MapAllProperties()
                .Build();
            var parameters = new DbParameter[] { 
                    this._db.CreateParameter("PageIndex", pageIndex, DbType.Int32),
                    this._db.CreateParameter("PageSize", pageSize, DbType.Int32),
                    this._db.CreateParameter("TotalCounts", 0, DbType.Int32, ParameterDirection.Output),
                    this._db.CreateParameter("OrderClause", orderClause, DbType.String),
                    this._db.CreateParameter("WhereClause", whereClause, DbType.String)
                };
            var lst = this._db.Execute("SP_Product_GetList", map, parameters).ToList();
            total = (int)parameters[2].Value;

            return lst;
        }

        public Product GetDetail(int id)
        {
            var map = TNMapBuilder<Product>
                .MapAllProperties()
                .Map(m => m.LstGroup).WithFunc((row) =>
                {
                    if (row["LstGroup"] != DBNull.Value)
                    {
                        var lstInt = this.GetValue<List<ListIntItem>>(Convert.ToString(row["LstGroup"]));

                        return lstInt.Select(m => m.Id).ToList();
                    }
                    else
                    {
                        return new List<int>();
                    }
                })
                .Build();
            var query = this._db.CreateSprocAccessor("SP_Product_GetDetail", map);

            return query.Execute(id).FirstOrDefault();
        }

        public int Insert(Product detail)
        {
            var map = new IntegerResultSetMapper();
            var query = this._db.CreateSprocAccessor("SP_Product_Insert", map);

            return query.Execute(
                detail.Name,
                detail.Summary,
                detail.Description,
                detail.Price,
                detail.CreatedBy,
                detail.IsActive
            ).FirstOrDefault();
        }

        public int Update(Product detail)
        {
            var map = new IntegerResultSetMapper();
            var query = this._db.CreateSprocAccessor("SP_Product_Update", map);

            return query.Execute(
                detail.Id,
                detail.Name,
                detail.Summary,
                detail.Description,
                detail.Price,
                detail.UpdatedBy,
                detail.IsActive
            ).FirstOrDefault();
        }

        #endregion

        #region Product Group

        public List<ProductGroup> GetListGroup(int pageIndex, int pageSize, out int total, string orderClause, string whereClause)
        {
            var map = TNMapBuilder<ProductGroup>
                .MapAllProperties()
                .Build();
            var parameters = new DbParameter[] { 
                    this._db.CreateParameter("PageIndex", pageIndex, DbType.Int32),
                    this._db.CreateParameter("PageSize", pageSize, DbType.Int32),
                    this._db.CreateParameter("TotalCounts", 0, DbType.Int32, ParameterDirection.Output),
                    this._db.CreateParameter("OrderClause", orderClause, DbType.String),
                    this._db.CreateParameter("WhereClause", whereClause, DbType.String)
                };
            var lst = this._db.Execute("SP_Product_GetListGroup", map, parameters).ToList();
            total = (int)parameters[2].Value;

            return lst;
        }

        public ProductGroup GetDetailGroup(int id)
        {
            var map = TNMapBuilder<ProductGroup>
                .MapAllProperties()
                .Build();
            var query = this._db.CreateSprocAccessor("SP_Product_GetDetailGroup", map);

            return query.Execute(id).FirstOrDefault();
        }

        public int InsertGroup(ProductGroup detail)
        {
            var map = new IntegerResultSetMapper();
            var query = this._db.CreateSprocAccessor("SP_Product_InsertGroup", map);

            return query.Execute(
                detail.Key,
                detail.Name,
                detail.Description,
                detail.IsActive,
                detail.CreatedBy
            ).FirstOrDefault();
        }

        public int UpdateGroup(ProductGroup detail)
        {
            var map = new IntegerResultSetMapper();
            var query = this._db.CreateSprocAccessor("SP_Product_UpdateGroup", map);

            return query.Execute(
                detail.Id,
                detail.Key,
                detail.Name,
                detail.Description,
                detail.IsActive,
                detail.UpdatedBy
            ).FirstOrDefault();
        }

        #endregion
    }
}
